package com.pinhuba.bams.framework.http;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.List;

import javax.net.ssl.SSLHandshakeException;

import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.ParseException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import android.util.Log;
import com.pinhuba.bams.framework.ConfigProperties;
import com.pinhuba.bams.framework.exception.NetworkException;
import com.pinhuba.bams.framework.exception.TimeoutException;
import com.pinhuba.bams.framework.util.Loger;

public class BaseHttp {

	protected static final String ENCODING = ConfigProperties.ENCODING;

	/**
	 * From ConnectionManager management of connection pool out of the
	 * connection overtime time, set up here for 8 seconds When
	 * ConnectionPoolTimeoutException overtime cast (is ConnectTimeoutException
	 * classes)
	 */
	private static final int CONNECTION_POOL_TIMEOUT = ConfigProperties.TIMEOUT;
	/**
	 * Defines the connection to a server overtime time, here set to 8 seconds,
	 * when ConnectTimeoutException into overtime
	 */
	private static final int CONNECTION_TIMEOUT = ConfigProperties.TIMEOUT;

	/**
	 * Define the read data from the network of overtime time, here set to 8
	 * seconds, when SocketTimeoutException into overtime
	 */
	private static final int SOCKET_TIMEOUT = ConfigProperties.TIMEOUT;

	private static CookieStore CS = null;
	private static final String TAG = "BaseHttp";

	// private static DefaultHttpClient client = null;

	private static HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
		public boolean retryRequest(IOException exception, int executionCount,
				HttpContext context) {
			if (executionCount >= 5) {
				// 如果超过最大重试次数，那么就不要继续了
				return false;
			}
			if (exception instanceof NoHttpResponseException) {
				// 如果服务器丢掉了连接，那么就重试
				return true;
			}
			if (exception instanceof SSLHandshakeException) {
				// 不要重试SSL握手异常
				return false;
			}
			HttpRequest request = (HttpRequest) context
					.getAttribute(ExecutionContext.HTTP_REQUEST);
			boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
			if (idempotent) {
				// 如果请求被认为是幂等的，那么就重试
				return true;
			}
			return false;
		}
	};

	public static String sendRequest(HttpUriRequest request)
			throws TimeoutException, NetworkException, IOException {
		DefaultHttpClient client = null;
		String result = "";
		try {
			if (client == null) {
				client = buildClient(CONNECTION_POOL_TIMEOUT,
						CONNECTION_TIMEOUT, SOCKET_TIMEOUT);
			}
			if (CS != null)
				client.setCookieStore(CS);
			HttpResponse response = client.execute(request);

			if (response.getEntity() != null) {
				result = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
				final int statusCode = response.getStatusLine().getStatusCode();
				if (statusCode == 200) {
					final List<Cookie> cookies = client.getCookieStore()
							.getCookies();
					if (cookies.isEmpty()) {

					} else {
						CS = client.getCookieStore();
						for (int i = 0; i < cookies.size(); i++) {
							Log.i(TAG, "- domain " + cookies.get(i).getDomain());
							Log.i(TAG, "- path " + cookies.get(i).getPath());
							Log.i(TAG, "- value " + cookies.get(i).getValue());
							Log.i(TAG, "- name " + cookies.get(i).getName());
							Log.i(TAG, "- port " + cookies.get(i).getPorts());
							Log.i(TAG, "- comment "
									+ cookies.get(i).getComment());
							Log.i(TAG, "- commenturl"
									+ cookies.get(i).getCommentURL());
							Log.i(TAG, "- all " + cookies.get(i).toString());
						}
					}
				}
			}
		} catch (ConnectTimeoutException e) {
			throw new TimeoutException(e.getMessage(), e);
		} catch (SocketTimeoutException e) {
			throw new TimeoutException(e.getMessage());
		} catch (ParseException e) {
			Loger.d("The ParseException is:");
			e.printStackTrace();
			throw new IOException();
		} catch (IOException e) {
			Loger.d("The result is:" + result);
			Loger.d("The IOException is:");
			e.printStackTrace();
			throw new IOException();
		} finally {
			if (client != null) {
				HttpClientHelper.closeClient(client);
			}
		}
//		Loger.d("The result is:" + result);
		return result;
	}

	private static DefaultHttpClient buildClient(int connectionPoolTimeout,
			int connectionTimeout, int socketTimeout) {
		return HttpClientHelper.buildHttpClient(connectionPoolTimeout,
				connectionTimeout, socketTimeout);
	}
}
